using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;
using FeedAntGame.Support;
using FeedAntGame.Component.Dialog;
using FeedAntGame.Component;
using FeedAntGame.Sprite;
using FeedAntGame.Control;
namespace FeedAntGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public partial class GameFA : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics; // share widthScale child class of BaseSprite if need
        SpriteBatch spriteBatch;
        SpriteFont fpsFont;
        SpriteFont gridFont;
        //Component
        public PlayManager playManager;
        public MainMenu mainMenu;
        public GameOver gameOver;
        public PickCandyDlg pickCandy;
        OptionDlg optionDlg;
        PauseDlg pauseDlg;
        SaveScoreDlg saveScoreDlg;
        HighScoreDlg highScoreDlg;
        MenuDlg menuDlg;
        PlayAgainDlg playAgainDlg;
        //Audio
        AudioEngine audioEngine;
        AudioCategory musicCategory;
        WaveBank waveBank;
        SoundBank soundBank;
        Cue trackCue = null;
        float musicVolume = 1.0f;
        //General random variable
        public Random rnd;

        //Score
        public int currentScore = 0;
        public SpriteFont scoreFont;
        
        //Cursor
        private Cursor cursor;

        internal Cursor Cursor
        {
            get { return cursor; }            
        }

        //Current directory
        public string ConnectionString;

        
        //Loading percent
        public int LoadingPercent = 0; // use in future
        
        //List sprite
        List<Grid> gridList = new List<Grid>();

        /************************************************************************/
        /*                      Get/Set                                                                     */
        /************************************************************************/
        /// <summary>
        /// Get GraphicsDeviceManager of Game
        /// </summary>
        public GraphicsDeviceManager Graphics
        {
            get { return graphics; }
        }

        /************************************************************************/
        /*                  Constructor                                                                     */
        /************************************************************************/
        public GameFA()
        {

            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.IsFullScreen = false;
            graphics.PreferredBackBufferHeight = 600;
            graphics.PreferredBackBufferWidth = 800;
            graphics.SynchronizeWithVerticalRetrace = true;  //can be false but then you just draw as many frames your machine is able to...
            this.IsFixedTimeStep = false;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: AddOneCandyFeed your initialization logic here
            // change graphics size            
            Database.InitDatabase();
            //--------------------------Global variables----------------------------------------
            // sound
            audioEngine = new AudioEngine(@"Content\Audio\GameAudio.xgs");
            waveBank = new WaveBank(audioEngine, @"Content\Audio\Wave Bank.xwb");
            soundBank = new SoundBank(audioEngine, @"Content\Audio\Sound Bank.xsb");
            musicCategory = audioEngine.GetCategory("Music");
            // score
            scoreFont = Content.Load<SpriteFont>(@"fonts\score");

            // cursor
            cursor = new Cursor(Content.Load<Texture2D>(@"Images\cursor_normal"), Vector2.Zero, new Point(24, 24),
                0, new Point(0, 0), new Point(1, 1), this.Content);

            //-------------------------------Screens-----------------------------------------------
            
            // main menu
            mainMenu = new MainMenu(this);
            mainMenu.Enabled = false;
            mainMenu.Visible = false;
            Components.Add(mainMenu);
            // play manager
            playManager = new PlayManager(this);
            playManager.Enabled = false;
            playManager.Visible = false;
            Components.Add(playManager);
            // pick candyFeed
            pickCandy = new PickCandyDlg(this);
            pickCandy.Enabled = false;
            pickCandy.Visible = false;
            Components.Add(pickCandy);
            // game over
            gameOver = new GameOver(this);
            gameOver.Enabled = false;
            gameOver.Visible = false;
            Components.Add(gameOver);
            // pause dialog
            pauseDlg = new PauseDlg(this);
            pauseDlg.Enabled = false;
            pauseDlg.Visible = false;
            Components.Add(pauseDlg);
            // option dialog
            optionDlg = new OptionDlg(this);
            optionDlg.Enabled = false;
            optionDlg.Visible = false;
            Components.Add(optionDlg);
            // save score dialog
            saveScoreDlg = new SaveScoreDlg(this);
            saveScoreDlg.Enabled = false;
            saveScoreDlg.Visible = false;
            Components.Add(saveScoreDlg);
            // high score dialog
            highScoreDlg = new HighScoreDlg(this);
            highScoreDlg.Enabled = false;
            highScoreDlg.Visible = false;
            Components.Add(highScoreDlg);
            // menu dialog
            menuDlg = new MenuDlg(this);
            menuDlg.Enabled = false;
            menuDlg.Visible = false;
            Components.Add(menuDlg);
            // play again dialog
            playAgainDlg = new PlayAgainDlg(this);
            playAgainDlg.Enabled = false;
            playAgainDlg.Visible = false;
            Components.Add(playAgainDlg);

            //set main menu to display
            mainMenu.Visible = true;
            mainMenu.Enabled = true;

            // global random variable
            rnd = new Random();

            // set connection string data file to current directory
            string currentDir = Directory.GetCurrentDirectory();
            ConnectionString = "Data Source=.\\SQLEXPRESS;Integrated Security=True;Connect Timeout=30;User Instance=True;AttachDbFilename=" + currentDir + "\\";
            
            // set exiting event
            this.Exiting += new EventHandler<EventArgs>(GameFA_Exiting);
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            fpsFont = Content.Load<SpriteFont>(@"Fonts\Score");
            gridFont = Content.Load<SpriteFont>(@"Fonts\gridValue");
            // TODO: use this.Content to load your game content here

            generateGrid(40, 40);

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            FrameCounter.frame_shown();

            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                this.Exit();

            // TODO: AddOneCandyFeed your update logic here  

            cursor.Update(gameTime, Window.ClientBounds);
            cursor.State = Cursor.STATE_TYPE.NORMAL;
            //Audio update
            musicCategory.SetVolume(musicVolume);
            audioEngine.Update();
            

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            // TODO: AddOneCandyFeed your drawing code here
            
            
            base.Draw(gameTime);

            long fps = FrameCounter.get_framerate();
            spriteBatch.Begin();
            // Draw Frame per second
            if(fps>0)
                spriteBatch.DrawString(fpsFont, "FPS: " + fps.ToString(), new Vector2(50, 50), Color.White);
            // Draw Cursor
            cursor.Draw(gameTime, spriteBatch);

            // Draw grid 
            foreach (Grid s in gridList)
            {
                s.Sprite.Draw(gameTime, spriteBatch);
                spriteBatch.DrawString(gridFont, s.Value.ToString(), s.Sprite.Position, Color.White);
            }

            spriteBatch.End();
        }

        private void generateGrid(int rowDistance, int columnDistance)
        {
            int x = 0;
            int y = 0;
            //Insert column
            for (x = 0; x <= this.Window.ClientBounds.Width; x += columnDistance)
            {
                Grid column = new Grid(this, Grid.TYPE.COLUMN_LINE, new Vector2(x, y));
                column.Value = x;
                column.Sprite.ScaleWidth = 1.0f/4;
                column.Sprite.ScaleHeight = this.Window.ClientBounds.Height/column.Sprite.RealHeight;
                gridList.Add(column);
            }
            //Insert row
            x = 0;
            for (y = 0; y <= this.Window.ClientBounds.Height; y += rowDistance)
            {
                Grid row = new Grid(this, Grid.TYPE.ROW_LINE, new Vector2(x, y));
                row.Value = y;
                row.Sprite.ScaleHeight = 1.0f / 2;
                row.Sprite.ScaleWidth = this.Window.ClientBounds.Width / row.Sprite.Width;
                gridList.Add(row);
            }

        }
        /// <summary>
        /// 1.0f == 100%
        /// </summary>
        /// <param name="percent"></param>
        public void Volume(float percent, string category)
        {
            musicCategory = audioEngine.GetCategory(category);
            musicVolume = percent;
        }
        public Cue PlayCue(string cueName)
        {            
            this.trackCue = soundBank.GetCue(cueName);
            if (!trackCue.IsPlaying)
            {
                this.trackCue.Play();  
            }          
            return this.trackCue;
        }

        public void StopCue(Cue cue, AudioStopOptions option)
        {
            if (cue!= null)
            {
                if (cue.IsPlaying)
                {
                    cue.Stop(option);
                    cue = null;
                }
            }
            
        }
        public void AddScore(int score)
        {
            currentScore += score;
        }

        //Switching  screens
        public void GoToMainMenu()
        {
            
            for (int i = 0; i < Components.Count; i++)
            {
                IGameComponent component = Components.ElementAt(i);
                DrawableGameComponent c = (DrawableGameComponent)component;
                if (component is MainMenu)
                {
                    c.Enabled = true;
                    c.Visible = true;
                }
                else
                {
                    c.Enabled = false;
                    c.Visible = false;
                }
            }
        }

        public void GoToPlayGame()
        {            
            for (int i = 0; i < Components.Count; i++)
            {
                IGameComponent component = Components.ElementAt(i);
                DrawableGameComponent c = (DrawableGameComponent)component;
                if (component is PlayManager)
                {
                    c.Enabled = true;
                    c.Visible = true;

                }
                else if (component is PickCandyDlg)
                {
                    
                }
                else
                {
                    c.Enabled = false;
                    c.Visible = false;
                }
            }
        }

        public void OpenPickCandy()
        {
            pickCandy.Start(playManager.GetCurrentLevel());
            
        }

        public void ClosePickCandy()
        {
            pickCandy.Finish(playManager);
            playManager.gameState = GameState.READY;
              
        }

        public void OpenPauseDlg()
        {
            pauseDlg.Start();
        }

        public void OpenOptionDlg()
        {
            optionDlg.Start();
        }

        public void OpenSaveScoreDlg()
        {
            saveScoreDlg.Start();
        }
        public void OpenHighScoreDlg()
        {
            highScoreDlg.Start();
        }
        public void OpenMenuDlg()
        {
            menuDlg.Start();
        }

        public void OpenPlayAgainDlg()
        {
            playAgainDlg.Start();
        }
        private void GameFA_Exiting(object sender, EventArgs args)
        {
            if (playManager.Visible == true)
            {
                Database.Hien_Trang.LuuHienTrang(playManager.GetCurrentLevel(), (int)playManager.GetLastScore());
            }
        }
        protected override void OnDeactivated(object sender, EventArgs args)
        {
            if (playManager.Enabled == true)
            {
                playManager.Enabled = false;
                playManager.cancelPutCandy();
                OpenPauseDlg();
            }
            Volume(0, "Music");
            base.OnDeactivated(sender, args);
        }

        protected override void OnActivated(object sender, EventArgs args)
        {
            Volume(1, "Music");
            base.OnActivated(sender, args);
        }

        public void setFullScreen(bool active)
        {
            graphics.IsFullScreen = active;
            graphics.ApplyChanges();
        }

        
    }
}
